﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Auth.Application.Dtos;
using Auth.Domain.TableEntity;
using AutoMapper;
using Auth.Repository.IRepositories;
using Auth.Utility;
using SqlSugar;

namespace Auth.Application
{
    public class MenuAppService : IMenuAppService
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;

        public MenuAppService(IMenuRepository menuRepository, IUserRepository userRepository,
            IRoleRepository roleRepository)
        {
            _menuRepository = menuRepository;
            _userRepository = userRepository;
            _roleRepository = roleRepository;
        }

        public int Delete(List<string> ids)
        {
            return _menuRepository.Delete(ids);
        }
        public int Insert(MenuDto entity)
        {
            var exist = _menuRepository.Any(s => s.Name == entity.Name || s.Code == entity.Code);
            if (exist)
                throw new MessageBox("菜单名称或编号重复！");
            return _menuRepository.InsertWithCache(Mapper.Map<menus>(entity));
        }

        public int InsertRange(List<MenuDto> entities)
        {
            return _menuRepository.InsertRangeWithCache(Mapper.Map<List<menus>>(entities));
        }

        public int Update(MenuDto entity)
        {
            return _menuRepository.UpdateWithCache(Mapper.Map<menus>(entity));
        }

        public List<MenuDto> GetAllList()
        {
            var menus = _menuRepository.QueryAllWithCache().OrderBy(it => it.SerialNumber);
            return Mapper.Map<List<MenuDto>>(menus);
        }

        public bool InsertOrUpdate(MenuDto dto)
        {
            if (string.IsNullOrEmpty(dto.Id))
            {
                dto.Id = Guid.NewGuid().ToString();
                return Insert(dto) > 0;
            }
            return Update(dto) > 0;
        }

        public MenuDto Get(string id)
        {
            return Mapper.Map<MenuDto>(_menuRepository.QuerySingle(id));
        }

        /// <summary>
        /// 根据用户获取功能菜单
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        public List<MenuDto> GetMenusByUser(string userId)
        {
            List<MenuDto> result = new List<MenuDto>();
            var allMenus = _menuRepository.QueryByWhereWithCache(it => it.Type == 0, s => SqlFunc.ToDecimal(s.No));
            if (userId == Guid.Empty.ToString()) //超级管理员
                return Mapper.Map<List<MenuDto>>(allMenus);
            var user = _userRepository.GetWithRoles(userId);
            if (user == null)
                return result;
            var userRoles = user.UserRoles;
            List<string> menuIds = new List<string>();
            foreach (var role in userRoles)
            {
                menuIds = menuIds.Union(_roleRepository.GetAllMenuListByRole(role.RoleId)).ToList();
            }

            allMenus = allMenus.Where(it => menuIds.Contains(it.Id)).OrderBy(it => it.SerialNumber).ToList();
            return Mapper.Map<List<MenuDto>>(allMenus);
        }


        /// <summary>
        /// 生成下级菜单编号
        /// </summary>
        /// <param name="menuId"></param>
        /// <returns></returns>
        public string GetNextNo(string menuId)
        {
            var parentMenu = Get(menuId);
            Expression<Func<menus, bool>> filter = s => s.ParentId == menuId;
            //根据编号的降排序
            var childMenuList = _menuRepository.QueryByWhereWithCache(filter, s => SqlFunc.ToDecimal(s.No), OrderByType.Desc);
            //当前菜单没有下级菜单则返回当前菜单编号*100+1 ，例：当前编号为1，则返回101
            if (childMenuList.Count < 1)
            {
                return parentMenu != null ? (decimal.Parse(parentMenu.No) * 100 + 1).ToString("#") : "";
            }

            //如果已经包含下级菜单，返回下级菜单最大编号+1
            return (decimal.Parse(childMenuList[0].No) + 1).ToString("#");
        }

        /// <summary>
        /// 获取同级菜单No
        /// </summary>
        /// <param name="menuId"></param>
        /// <returns></returns>
        public string GetNo(string menuId)
        {
            var menu = Get(menuId);
            Expression<Func<menus, bool>> filter = s => s.ParentId == menu.ParentId;
            //根据编号的降排序
            var childMenuList = _menuRepository.QueryByWhereWithCache(filter, s => SqlFunc.ToDecimal(s.No), OrderByType.Desc);

            //菜单最大编号+1
            return (decimal.Parse(childMenuList[0].No) + 1).ToString("#");
        }

        public LayuiTableModel<MenuDto> GetTableList(int page, int size, List<IConditionalModel> searchParam, string orderFields)
        {
            LayuiTableModel<MenuDto> tableModel = new LayuiTableModel<MenuDto>
            {
                Success = true,
                Code = 0,
                Count = _menuRepository.QueryCount(searchParam),
                Data = Mapper.Map<List<MenuDto>>(_menuRepository.QueryByWherePage(page, size, searchParam, orderFields))
            };
            return tableModel;
        }

        public MenuDto QuerySingle(string id)
        {
            return Mapper.Map<MenuDto>(_menuRepository.QuerySingle(id));
        }
    }
}